import { nextTick, onUnmounted, ref, watch } from "vue";
import type { ComputedRef, Ref } from "vue";
import { useElementSize } from "@vueuse/core";
import { BarChart, GaugeChart, LineChart, PictorialBarChart, PieChart, RadarChart, ScatterChart } from "echarts/charts";
import type {
  BarSeriesOption,
  GaugeSeriesOption,
  LineSeriesOption,
  PictorialBarSeriesOption,
  PieSeriesOption,
  RadarSeriesOption,
  ScatterSeriesOption,
} from "echarts/charts";
import {
  DatasetComponent,
  GridComponent,
  LegendComponent,
  TitleComponent,
  ToolboxComponent,
  TooltipComponent,
  TransformComponent,
} from "echarts/components";
import type {
  DatasetComponentOption,
  GridComponentOption,
  LegendComponentOption,
  TitleComponentOption,
  ToolboxComponentOption,
  TooltipComponentOption,
} from "echarts/components";
import * as echarts from "echarts/core";
import { LabelLayout, UniversalTransition } from "echarts/features";
import { CanvasRenderer } from "echarts/renderers";

export type ECOption = echarts.ComposeOption<
  | BarSeriesOption
  | LineSeriesOption
  | PieSeriesOption
  | ScatterSeriesOption
  | PictorialBarSeriesOption
  | RadarSeriesOption
  | GaugeSeriesOption
  | TitleComponentOption
  | LegendComponentOption
  | TooltipComponentOption
  | GridComponentOption
  | ToolboxComponentOption
  | DatasetComponentOption
  >;

echarts.use([
  TitleComponent,
  LegendComponent,
  TooltipComponent,
  GridComponent,
  DatasetComponent,
  TransformComponent,
  ToolboxComponent,
  BarChart,
  LineChart,
  PieChart,
  ScatterChart,
  PictorialBarChart,
  RadarChart,
  GaugeChart,
  LabelLayout,
  UniversalTransition,
  CanvasRenderer,
]);

/**
 * Echarts hooks函数
 * @param options - 图表配置
 * @param renderFun - 图表渲染函数(例如：图表监听函数)
 * @description 按需引入图表组件，没注册的组件需要先引入
 */
export const useEcharts = (options: Ref<ECOption> | ComputedRef<ECOption>, renderFun?: (chartInstance: echarts.ECharts) => void) => {
  const domRef = ref<HTMLElement>();

  const initialSize = { width: 0, height: 0 };
  const { width, height } = useElementSize(domRef, initialSize);

  let chart: echarts.ECharts | null = null;

  const canRender = () => {
    return initialSize.width > 0 && initialSize.height > 0;
  };

  const isRendered = () => {
    return Boolean(domRef.value && chart);
  };

  const update = (updateOptions: ECOption) => {
    if (isRendered()) {
      chart!.setOption({ ...updateOptions, backgroundColor: "transparent" });
    }
  };

  const render = async () => {
    if (domRef.value) {
      await nextTick();
      chart = echarts.init(domRef.value);
      update(options.value);
      if (renderFun) {
        renderFun(chart);
      }
    }
  };
  const resize = () => {
    chart?.resize();
  };

  const destroy = () => {
    chart?.dispose();
  };

  const stopSizeWatch = watch([width, height], ([newWidth, newHeight]) => {
    initialSize.width = newWidth;
    initialSize.height = newHeight;
    if (newWidth === 0 && newHeight === 0) {
      // 节点被删除 将chart置为空
      chart = null;
    }
    if (canRender()) {
      if (!isRendered()) {
        render();
      } else {
        resize();
      }
    }
  });

  const stopOptionWatch = watch(options, (newValue) => {
    console.log({newValue});
    update(newValue);
  });

  onUnmounted(() => {
    destroy();
    stopSizeWatch();
    stopOptionWatch();
  });

  return {
    domRef,
  };
};
